// JavaScript Document
var ajaxHistory = {
	
historyImpl : {
	token : '',
	issueEvent : true,
	handlers : [],
	getToken : function() {
		return this.token ? this.token : '';
	},
	setToken : function(token) {
		this.token = token;
	},
	decodeFragment : function(encodedFragment) {
		// decodeURI() does *not* decode the '#' character.
		return decodeURI(encodedFragment.replace("%23", "#"));
	},
	encodeFragment : function(fragment) {
		// encodeURI() does *not* encode the '#' character.
		return encodeURI(fragment).replace("#", "%23");
	},
	getRawFragment : function() {
		//Firefox window.location.hash has be decoded, but other browsers no
		var href = window.location.href,
			index = href.indexOf('#');
		return (index != -1) ? href.substring(index + 1) : '';
	},
	eventSupported : function(eventName, el) {
		el = el || document.createElement("div");
		eventName = "on" + eventName;
		var isSupported = (eventName in el);
		if (el.setAttribute && !isSupported) {
			el.setAttribute(eventName, "return;");
			isSupported = typeof el[eventName] === "function";
	  	}
	  	el = null;
	  	return isSupported;
	},
	init : function() {
		var token = this.decodeFragment(this.getRawFragment()),
			that = this;
		this.setToken(token);
		
		if (!this.eventSupported('hashchange', window)) {
			this.monitoringHistory();
		}
		this.addHashChangedEventListener(function() {
			if (!that.issueEvent) {
				that.issueEvent = true;
				return;
			}
			var token = that.decodeFragment(that.getRawFragment());
			that.newItemOnEvent(token);
		});
	},
	newItem : function(historyToken, issueEvent) {
		historyToken = historyToken ? historyToken : '';
		if (historyToken !== this.getToken()) {
			this.issueEvent = issueEvent;
			this.setToken(historyToken);
			this.updateHistory(historyToken);
			if (!this.eventSupported('hashchange', window)) {
				this.fireHashChangedEvent();
			}
		}
	},
	newItemOnEvent : function(historyToken) {
		this.setToken(historyToken);
		this.fireCallback(historyToken);
	},
	fireCallback : function(token) {
		var handlers = this.handlers;
		for (var i in handlers) {
			try {
				handlers[i].call(this, token);
			} catch(e) {
				//ignore
			}
		}
	},
	updateHistory : function(historyToken) {
		window.location.hash = this.encodeFragment(historyToken);
	},
	addHashChangedEventListener : function(callback){
		if (window.addEventListener) {
			window.addEventListener('hashchange', callback, false);
		} else if (window.attachEvent) {
			window.attachEvent('onhashchange', callback);
		}
	},
	fireHashChangedEvent : function() {
		var event;
		if (document.createEvent) {
			event = document.createEvent('Events');
			event.initEvent('hashchange', true, false);
		} else if (document.createEventObject) {
			event = document.createEventObject();
		} else {
			return;
		}
		if (window.dispatchEvent) {
			window.dispatchEvent(event);
		} else if (window.fireEvent) {
			window.fireEvent('onhashchange', event);
		}
	},
	monitoringHistory : function() {
		var that = this,
			caller = arguments.callee,
			oldToken = this.getToken(),
			newToken = this.decodeFragment(this.getRawFragment());
		if (oldToken !== newToken) {
			this.fireHashChangedEvent();
		}
		setTimeout(function(){caller.call(that)}, 500);
	}
},
init : function() {
	this.historyImpl.init();
},
back : function() {
	window.history.back();
},
forward : function() {
	window.history.forward();
},
getToken : function() {
	return this.historyImpl.getToken();
},
newItem : function(historyToken) {
	this.historyImpl.newItem(historyToken, true);
},
newItem : function(historyToken, issueEvent) {
	this.historyImpl.newItem(historyToken, issueEvent);
},
addHistoryChangeHandler : function(handler) {
	if (typeof handler !== 'function') {
		return;
	}
	this.historyImpl.handlers.push(handler);
},
removeHistoryChangeHandler : function(handler) {
	if (typeof handler !== 'function') {
		return;
	}
	var handlers = this.historyImpl.handlers;
	for (var i in handlers) {
		if (handlers[i] === handler) {
			handlers.splice(i, 1);
			break;
		}
	}
},
getHistoryChangeHandlerSize : function() {
	return this.historyImpl.handlers.length;
},
getRawFragment : function() {
	return this.historyImpl.getRawFragment();
},
getDecodedFragment : function() {
	return this.historyImpl.decodeFragment(this.getRawFragment());
}

//ajaxHistory defined end
};